package com.thrift.client.config;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.pool.impl.GenericObjectPool;

/**
 * @author 何锦涛--CodeSleep
 * @since 2022/9/5 21:07
 */
@Slf4j
public class ThriftClientConnectPoolFactory {

    // 对象池
    public GenericObjectPool<TTSocket> pool;
    public String host;
    public Integer port;

    // 实例化池工厂帮助类
    public ThriftClientConnectPoolFactory(GenericObjectPool.Config config, String ip, int port, String serviceName) {
        ConnectionFactory connectionFactory = new ConnectionFactory(ip, port, serviceName);
        this.host = ip;
        this.port = port;
        // 实例化池对象
        this.pool = new GenericObjectPool<TTSocket>(connectionFactory, config);
        // 设置获取对象前校验对象是否可以
        this.pool.setTestOnBorrow(true);
    }

    /**
     * 在池中获取一个空闲的对象
     * 如果没有空闲且池子没满，就会调用 makeObject 创建一个新的对象
     * 如果满了，就会阻塞等待，直到有空闲对象或者超时
     */
    public TTSocket getConnect() throws Exception {
        try {
            return (TTSocket) pool.borrowObject();
        } catch (Exception e) {
            // 如果为空，说明服务端没有创建连接，先创建一个假连接
            return new TTSocket("localhost", 7777, "fake-socket");
        }
    }

    // 取得权重值
    public double getWeight() {
        //活动的连接数 除以 最大连接数
        double numActive = pool.getNumActive();
        double maxTotal = pool.getMaxActive();
        log.info("计算权重的活动链接数为： [" + numActive + " ] 最大连接数为 [" + maxTotal + "]");
        return numActive / maxTotal;
    }

    // 将对象从池中移除
    public void invalidateObject(TTSocket socket) {
        try {
            pool.invalidateObject(socket);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 将一个用完的对象返还给对象池
    public void returnConnection(TTSocket socket) {
        try {
            pool.returnObject(socket);
        } catch (Exception e) {
            if (socket != null) {
                try {
                    socket.close();
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }
    }
}
